﻿using FlyingEye.Common.Utils;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IO;
using System.Text;

namespace FlyingEye.Extensions
{
    public static class JwtExtensions
    {
        public static IServiceCollection AddJwtBearerService(this IServiceCollection services)
        {
            // 从配置文件中获取 JWT 配置。
            var provider = services.BuildServiceProvider();
            var configuration = provider.GetRequiredService<IConfiguration>();
            var jwtConfig = configuration.GetSection("Jwt");

            // 获取密钥并生成公钥。
            var secretFile = jwtConfig.GetValue<string>("Secret");

            if (string.IsNullOrWhiteSpace(secretFile) || !File.Exists(secretFile))
            {
                throw new InvalidOperationException("Jwt Secret 配置无效。");
            }

            var applicationConfiguration = provider.GetRequiredService<ApplicationConfiguration>();
            var signingKey = new SymmetricSecurityKey(applicationConfiguration.JwtSecretRowData);

            // 配置认证参数。
            services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                })
            .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,    // 是否验证签名,不验证的画可以篡改数据，不安全。
                        IssuerSigningKey = signingKey,      // 公钥。
                        ValidateIssuer = true,              // 是否验证发行人，就是验证载荷中的Iss是否对应ValidIssuer参数。
                        ValidIssuer = jwtConfig.GetValue<string>("Issuer"),      // 发行人/组织。
                        ValidateAudience = true,                                 // 是否验证订阅人，就是验证载荷中的Aud是否对应ValidAudience参数。
                        ValidAudience = jwtConfig.GetValue<string>("Audience"),  // 订阅人/组织。
                        ValidateLifetime = true,                                 // 是否验证过期时间，过期了就拒绝访问。
                        ClockSkew = TimeSpan.Zero,    //这个是缓冲过期时间，也就是说，即使我们配置了过期时间，这里也要考虑进去，过期时间+缓冲，默认好像是7分钟，你可以直接设置为0。
                        RequireExpirationTime = true, // 设置需要过期时间。
                    };
                });

            return services;
        }
    }
}
